﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mrkz.ImageManipulation.SpatialFiltering
{
    public class SpatialFilterKernel
    {
        protected float[,] _kernel;
        protected int _size = 0;
        protected int _halfsize = 0;
        
        public SpatialFilterKernel(int Size)
        {
            if ((Size % 2) != 1)
                throw new ArgumentException("Kernel size must be Odd");

            _size = Size;
            _halfsize = (_size / 2);
            _kernel = new float[_size, _size];
        }
        
        public void setKernelElementWithRelativePosition(float ke,int column,int row){
            _kernel [column+_halfsize,row+_halfsize]=ke;
        }

        public int Size { get { return _size; } }

        public int LowSize { get { return -_size / 2; } }
        public int HighSize {get { return  _size / 2; } }

        public void setKernelElement(float ke, int column, int row)
        {
            _kernel[column+_halfsize, row+_halfsize] = ke;
        }

        /// <summary>
        /// The element 0,0 is the central element here
        /// </summary>
        /// <param name="column"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public float getKernelElementWithRelativePosition(int column,int row)
        {
            if (Math.Abs(row) > _halfsize)
                return 0;

            if (Math.Abs(column)>_halfsize)
                return 0;

            return _kernel[column+_halfsize,row+_halfsize];
        }

        /// <summary>
        /// Normalize the filter kernel so it doesn't change the average values in the final image
        /// </summary>
        public void NormalizeKernel()
        {
            float total=0;
            foreach (float f in _kernel)
                total += f;

            for (int i = 0; i < _size; i++)
                for (int j = 0; j < _size; j++)
                    _kernel[i, j] /= total;
        }


        public static SpatialFilterKernel operator *(SpatialFilterKernel A, float Factor)
        {
            SpatialFilterKernel R = new SpatialFilterKernel(A._size);

            for (int i = 0; i < A._size; i++)
                for (int j = 0; j < A._size; j++)
                    R._kernel[i, j] =A._kernel[i,j]*Factor;

            return R;
        }

        public virtual SpatialFilterKernel AdjustEffectIntensity(float factor)
        {
            return this * factor;
        }
    }
}
